<!--
 * @Description  : 
 * @Version      : 1.0
 * @Author       : seraph
 * @Date         : 2025-02-18 17:00:08
 * @LastEditors  : seraph
 * @LastEditTime : 2025-02-19 19:00:59
-->
<template>
    <h3>组件上使用 v-for</h3>
    <p>我们可以直接在组件上使用 v-for，和在一般的元素上使用没有区别 (别忘记提供一个 key)：</p>
    <pre><code class="html" v-html="highlighted(rawCode1, 'html')"></code></pre>
    <p>但是，这不会自动将任何数据传递给组件，因为组件有自己独立的作用域。为了将迭代后的数据传递到组件中，我们还需要传递 props：</p>
    <pre><code class="html" v-html="highlighted(rawCode2, 'html')"></code></pre>
    <p>不自动将 item 注入组件的原因是，这会使组件与 v-for 的工作方式紧密耦合。明确其数据的来源可以使组件在其他情况下重用。</p>
    <p>这里是一个简单的 Todo List 的例子，展示了如何通过 v-for 来渲染一个组件列表，并向每个实例中传入不同的数据。</p>
    <br>

    <p>App.vue</p>
    <pre><code class="html" v-html="highlighted(rawCode3, 'html')"></code></pre>
    <pre><code class="javascript" v-html="highlighted(rawCode4, 'javascript')"></code></pre>
    <p>TodoItem.vue</p>
    <pre><code class="html" v-html="highlighted(rawCode5, 'html')"></code></pre>
    <pre><code class="javascript" v-html="highlighted(rawCode6, 'javascript')"></code></pre>
</template>



<script lang="ts" setup>
import { ref, nextTick, watch, Ref, onMounted, reactive } from 'vue'
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css';
import javascript from 'highlight.js/lib/languages/javascript';
import html from 'highlight.js/lib/languages/xml';

hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('html', html);

const highlighted = (code: string, type: string) => {
    return hljs.highlight(code, { language: type }).value.replace(/&amp;lt;/g, '&lt;').replace(/&amp;gt;/g, '&gt;')
}

const getRenderingHTML = (items: { element: Ref<HTMLElement | null>; html: Ref<string> }[]) => {
    items.forEach((item) => {
        nextTick(() => {
            if (item.element.value) {
                item.html.value = item.element.value.outerHTML
            }
        })
    })
}

const rawCode1 = `<MyComponent v-for="item in items" :key="item.id" />`

const rawCode2 = `<MyComponent
  v-for="(item, index) in items"
  :item="item"
  :index="index"
  :key="item.id"
/>`

const rawCode3 = `<template>
	<form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    />
    <button>Add</button>
  </form>
  <ul>
    <todo-item
      v-for="(todo, index) in todos"
      :key="todo.id"
      :title="todo.title"
      @remove="todos.splice(index, 1)"
    ></todo-item>
  </ul>
</template>`

const rawCode4 = `<script setup>
import { ref } from 'vue'
import TodoItem from './TodoItem.vue'
  
const newTodoText = ref('')
const todos = ref([
  {
    id: 1,
    title: 'Do the dishes'
  },
  {
    id: 2,
    title: 'Take out the trash'
  },
  {
    id: 3,
    title: 'Mow the lawn'
  }
])

let nextTodoId = 4

function addNewTodo() {
  todos.value.push({
    id: nextTodoId++,
    title: newTodoText.value
  })
  newTodoText.value = ''
}
&lt;/script>`

const rawCode5 = `<template>
  <li>
    {{ title }}
    <button @click="$emit('remove')">Remove</button>
  </li>
</template>`

const rawCode6 = `<script setup>
defineProps(['title'])
defineEmits(['remove'])
&lt;/script>`






</script>


<style scoped>
p {
    font-size: 16px;
    padding: 2px;
    margin: 5px 0;
}

/* 设置预格式化文本的样式 */
pre {
    /* 背景色 */
    background-color: #f1ffed;
    /* 边框 */
    border: 1px solid #ccc;
    /* 缩小内边距 */
    padding: 5px 5px 5px 10px;
    /* 允许滚动 */
    overflow: auto;
    /* 可选：设置上下外边距 */
    margin: 0px 0;
    /* 允许换行 */
    /* normal: 连续的空白字符会被合并为一个空格。文本会在允许的断点处自动换行。
     nowrap：连续的空白字符会被合并为一个空格。文本不会自动换行，即使在允许的断点处也不会换行。
     pre：保留所有的空白字符（包括空格、制表符和换行符）。文本只会在遇到换行符或者 <br> 标签时换行。
     pre-wrap：保留所有的空白字符。文本会在遇到换行符、<br> 标签，或者达到容器边界时换行。
     pre-line：合并连续的空白字符为一个空格，但保留换行符。文本会在遇到换行符、<br> 标签，或者达到容器边界时换行。
   */
    white-space: pre-wrap;
    /* 行高 */
    line-height: 120%;
    /* 定义缩进 */
    tab-size: 4;
}

h3,
h4,
h5,
h6 {
    margin: 25px 0 10px 0;
    line-height: 100%;
}

.bolder {
    font-weight: bolder;
}

.red {
    color: red;
}

button {
    margin: 5px 5px 5px 10px;
    line-height: 150%;
    width: auto;
    padding: 0 10px;
}

.active {
    color: red;
}

.static {
    font-weight: bolder;
}

.text-danger {
    font-style: italic;
}
</style>
